package org.example.framework;

import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.*;
//配置信息读取类
public class BeanDefinitionReader {
    private Map<String,BeanDefinition> beanDefinitionMap;

    public Map<String,BeanDefinition> getBeanDefinitionMap() {
        return beanDefinitionMap;
    }
    public BeanDefinitionReader(){
        beanDefinitionMap=new HashMap<>();
    }
    public void getBeanDefinitions(String xml_file) throws MiniApplicationException{
        if (null == xml_file || "".equals(xml_file.trim())) {
            throw new MiniApplicationException(MiniApplicationException.ErrorType.FilePath_NULL,"未传入xml配置文件路径");

        }
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(xml_file);
        if(inputStream==null){
            throw new MiniApplicationException(MiniApplicationException.ErrorType.FILE_NOTFOUND,"未找到xml配置文件");

        }
        // 读取 xml 文件的内容
        SAXReader saxReader = new SAXReader();
        Map<String, String> map = new HashMap<String, String>();
        map.put("b", "http://www.springframework.org/schema/beans");
        try{
            saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
            Document document = saxReader.read(inputStream);
            List<Node> list = document.selectNodes("b:beans/b:bean");
            for (Node node : list) {
                if (!(node instanceof Element)) {
                    throw new MiniApplicationException(MiniApplicationException.ErrorType.File_READ_ERROR,"malformed bean config file.");
                }
                BeanDefinition beanDef = new BeanDefinition();
                parseBeanBase((Element) node, beanDef);
                for (Element element : ((Element) node).elements()) {
                    if("property".equals(element.getName())){
                        Property prop= parseBeanProperty(element);
                        beanDef.getPropertyList().add(prop);
                    }else if("constructor-arg".equals(element.getName())){
                        ConstructorArg arg=parseConstructorArg(element);
                        beanDef.getConstructorArgs().add(arg);
                    }
                }
                beanDefinitionMap.put(beanDef.getBeanName(), beanDef);
            }
        }
        catch (DocumentException e){
            throw new MiniApplicationException(MiniApplicationException.ErrorType.File_READ_ERROR,"读取xml文件内容失败");
        }

    }
    private static void parseBeanBase(Element element,BeanDefinition beanDefinition)
            throws MiniApplicationException{
        for(Attribute attribute:element.attributes()){
        if ("id".equals(attribute.getName())) {
            beanDefinition.setBeanName(attribute.getValue());
        } else if ("class".equals(attribute.getName())) {
            try {
                Class<?> clazz = Class.forName(attribute.getValue());
                beanDefinition.setBeanClass(clazz);
            } catch (ClassNotFoundException e) {
                throw new MiniApplicationException(MiniApplicationException.ErrorType.CLASS_NOTFOUND,"class not found:" + e.getMessage());
            }
        }
        }
    }
    /**
     * 解析Bean的属性定义
     * @param element
     * @return
     */
    private static Property parseBeanProperty(Element element) {
        Property property=new Property();
        for (Attribute attribute : element.attributes()) {
            if ("name".equals(attribute.getName())) {
                property.setName(attribute.getValue());
            } else if ("value".equals(attribute.getName())) {
                property.setValue(attribute.getValue());
            } else if ("ref".equals(attribute.getName())) {
                property.setRef(attribute.getValue());
            }
        }
        return property;
    }
    /**
     * 解析Bean的构造函数参数定义
     * @param element
     * @return
     * @throws MiniApplicationException
     */
    private static ConstructorArg parseConstructorArg(Element element) throws MiniApplicationException {
        ConstructorArg constructorArg=new ConstructorArg();
        for (Attribute attribute : element.attributes()) {
            if ("index".equals(attribute.getName())) {
                constructorArg.setIndex(Integer.parseInt(attribute.getValue()));
            }else if ("name".equals(attribute.getName())) {
                constructorArg.setName(attribute.getValue());
            }else if ("type".equals(attribute.getName())) {
                try {
                    String type=attribute.getValue();
                    Class<?> clazz=null;
                    if("int".equals(type)){
                        clazz=int.class;
                    }else if("float".equals(type)){
                        clazz=float.class;
                    }else if("double".equals(type)){
                        clazz=double.class;
                    }else{
                        clazz = Class.forName(type);
                    }
                    constructorArg.setType(clazz);
                } catch (ClassNotFoundException e) {
                    throw new MiniApplicationException(MiniApplicationException.ErrorType.CLASS_NOTFOUND,"class not found:" + e.getMessage());

                }
            }else if ("value".equals(attribute.getName())) {
                constructorArg.setValue(attribute.getValue());
            }else if ("ref".equals(attribute.getName())) {
                constructorArg.setRef(attribute.getValue());
            }
        }
        return constructorArg;
    }
}
